import {
	IParam,
	IUIEngineInputParam,
	IUIEngineModel,
	IUIEngineResult,
} from '@/core/interface';
import {
	calcCellStyle,
	calcHeaderCellStyle,
	calcHeaderRowStyle,
	calcRowStyle,
} from './util';
import { isFunction } from '@vue/shared';

/**
 * 界面引擎
 *
 * @export
 * @class UIEngine
 */
export class UIEngine<A> {
	/**
	 * 原始数据
	 *
	 * @protected
	 * @type {(IUIEngineModel)}
	 * @memberof UIEngine
	 */
	protected rowData: IUIEngineModel;

	/**
	 * Creates an instance of UIEngine.
	 * @param {IUIEngineModel} model
	 * @memberof UIEngine
	 */
	public constructor(model: IUIEngineModel) {
		this.rowData = model;
	}

	/**
	 * 异步执行
	 *
	 * @param {IUIEngineInputParam<A>} args
	 * @return {*}  {Promise<IUIEngineResult>}
	 * @memberof UIEngine
	 */
	public async asyncExcute(
		args: IUIEngineInputParam<A>
	): Promise<IUIEngineResult> {
		const { logicType } = this.rowData;
		if (!logicType) {
			return { ok: false, data: null };
		}
		switch (logicType) {
			case 'DEUILOGIC':
				return await this.asyncExecuteDEUILogic(args);
			case 'SYSVIEWLOGIC':
				return await this.asyncExecuteSysViewLogic(args);
			case 'APPVIEWUIACTION':
				return await this.asyncExecuteAppViewUIAction(args);
			case 'PFPLUGIN':
				return await this.asyncExecutePluginLogic(args);
			case 'SCRIPT':
				return await this.asyncExecuteScriptLogic(args);
			default:
				console.warn(`${logicType}暂未实现`);
				break;
		}
		return { ok: false, data: null };
	}

	/**
	 * 执行实体界面逻辑
	 *
	 * @param {IUIEngineInputParam<A>} args
	 * @return {*}  {Promise<IUIEngineResult>}
	 * @memberof UIEngine
	 */
	public async asyncExecuteDEUILogic(
		args: IUIEngineInputParam<A>
	): Promise<IUIEngineResult> {
		const { entityCodeName, logicName } = this.rowData;
		if (!entityCodeName || !logicName) {
			return { ok: false, data: [] };
		}
		const UIService = await App.getUIService(entityCodeName);
		if (!UIService) {
			return { ok: false, data: [] };
		}
		const { navContext, navParam, data, ability } = args;
		const result: IParam = await UIService.executeUILogic(
			logicName,
			navContext,
			navParam,
			[data],
			null,
			ability
		);
		// 需要考虑逻辑返回的是数组参数情况
		let ok = !(result.srfret === 'false' || result.srfref === false);
		if (result && result?.hasOwnProperty('srfret')) {
			delete result.srfret;
		}
		return { ok, data: [result] };
	}

	/**
	 * 执行系统预置界面逻辑
	 *
	 * @param {IUIEngineInputParam<A>} args
	 * @return {*}  {Promise<IUIEngineResult>}
	 * @memberof UIEngine
	 */
	public async asyncExecuteSysViewLogic(
		args: IUIEngineInputParam<A>
	): Promise<IUIEngineResult> {
		throw new Error('Method not implemented.');
	}

	/**
	 * 执行应用界面行为
	 *
	 * @param {IUIEngineInputParam<A>} args
	 * @return {*}  {Promise<IUIEngineResult>}
	 * @memberof UIEngine
	 */
	public async asyncExecuteAppViewUIAction(
		args: IUIEngineInputParam<A>
	): Promise<IUIEngineResult> {
		const { entityCodeName, uIActionTag } = this.rowData;
		if (!entityCodeName || !uIActionTag) {
			return { ok: false, data: [] };
		}
		const UIService = await App.getUIService(entityCodeName);
		if (!UIService || !isFunction(UIService[uIActionTag])) {
			return { ok: false, data: [] };
		}
		const { navContext, navParam, data, ability } = args;
		return await UIService[uIActionTag](
			navContext,
			navParam,
			[data],
			null,
			ability
		);
	}

	/**
	 * 执行界面插件逻辑
	 *
	 * @param {IUIEngineInputParam<A>} args
	 * @return {*}  {Promise<IUIEngineResult>}
	 * @memberof UIEngine
	 */
	public async asyncExecutePluginLogic(
		args: IUIEngineInputParam<A>
	): Promise<IUIEngineResult> {
		throw new Error('Method not implemented.');
	}

	/**
	 * 执行脚本代码逻辑
	 *
	 * @param {IUIEngineInputParam<A>} args
	 * @return {*}  {Promise<IUIEngineResult>}
	 * @memberof UIEngine
	 */
	public async asyncExecuteScriptLogic(
		args: IUIEngineInputParam<A>
	): Promise<IUIEngineResult> {
		const { scriptCode } = this.rowData;
		if (!scriptCode) {
			return { ok: false, data: null };
		}
		try {
			const { data } = args;
			eval(scriptCode);
			return { ok: true, data: data ? [data] : [] };
		} catch (error) {
			console.warn(`执行脚本界面逻辑异常，脚本代码为：${scriptCode}`);
		}
		return { ok: false, data: null };
	}

	/**
	 * 同步执行
	 *
	 * @param {IUIEngineInputParam<A>} args
	 * @memberof UIEngine
	 */
	public syncExcute(args: any): any {
		const { logicType, scriptCode, name } = this.rowData;
		if (!logicType || !scriptCode) {
			return { ok: false, data: null };
		}
		// 暂只支持脚本
		switch (logicType) {
			case 'SCRIPT':
				return this.dispenseUILogic(name, scriptCode, args);
			default:
				console.warn(`${logicType}暂未实现`);
				break;
		}
	}

	/**
	 * 分发UI逻辑参数
	 *
	 * @param {string} name
	 * @param {string} scriptCode
	 * @param {*} opts
	 * @return {*}
	 * @memberof UIEngine
	 */
	public dispenseUILogic(name: string, scriptCode: string, opts: any) {
		try {
			if (name) {
				switch (name.toLowerCase()) {
					case 'calcrowstyle':
						return calcRowStyle(opts, scriptCode);
					case 'calccellstyle':
						return calcCellStyle(opts, scriptCode);
					case 'calcheaderrowstyle':
						return calcHeaderRowStyle(opts, scriptCode);
					case 'calcheadercellstyle':
						return calcHeaderCellStyle(opts, scriptCode);
				}
			}
		} catch (error) {
			console.error(`执行脚本界面逻辑异常，脚本代码为：${scriptCode}`);
		}
	}
}
